home *** CD-ROM | disk | FTP | other *** search
/ MacAddict 83 / MacAddict_083_2003-07.iso / mac / Software / Development / VLC Source 0.5.3.dmg / src / input / input.c < prev   
C/C++ Source or Header  |  2003-04-07  |  20KB  |  609 lines

  1. /*****************************************************************************
  2.  * input.c: input thread
  3.  * Read an MPEG2 stream, demultiplex and parse it before sending it to
  4.  * decoders.
  5.  *****************************************************************************
  6.  * Copyright (C) 1998-2002 VideoLAN
  7.  * $Id: input.c,v 1.228 2003/03/30 01:13:37 massiot Exp $
  8.  *
  9.  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  24.  *****************************************************************************/
  25.  
  26. /*****************************************************************************
  27.  * Preamble
  28.  *****************************************************************************/
  29. #include <stdlib.h>
  30.  
  31. #include <vlc/vlc.h>
  32.  
  33. #include <string.h>
  34.  
  35. #ifdef HAVE_SYS_TIMES_H
  36. #   include <sys/times.h>
  37. #endif
  38.  
  39. #include "netutils.h"
  40. #include "vlc_playlist.h"
  41.  
  42. #include "stream_control.h"
  43. #include "input_ext-intf.h"
  44. #include "input_ext-dec.h"
  45. #include "input_ext-plugins.h"
  46.  
  47. #include "stream_output.h"
  48. #include <vlc/vout.h>
  49.  
  50. #include "interface.h"
  51.  
  52. /*****************************************************************************
  53.  * Local prototypes
  54.  *****************************************************************************/
  55. static  int RunThread       ( input_thread_t *p_input );
  56. static  int InitThread      ( input_thread_t *p_input );
  57. static void ErrorThread     ( input_thread_t *p_input );
  58. static void EndThread       ( input_thread_t *p_input );
  59.  
  60. /*****************************************************************************
  61.  * input_CreateThread: creates a new input thread
  62.  *****************************************************************************
  63.  * This function creates a new input, and returns a pointer
  64.  * to its description. On error, it returns NULL.
  65.  *****************************************************************************/
  66. input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
  67.                                       playlist_item_t *p_item )
  68. {
  69.     input_thread_t *    p_input;                        /* thread descriptor */
  70.     input_info_category_t * p_info;
  71.  
  72.     /* Allocate descriptor */
  73.     p_input = vlc_object_create( p_parent, VLC_OBJECT_INPUT );
  74.     if( p_input == NULL )
  75.     {
  76.         msg_Err( p_parent, "out of memory" );
  77.         return NULL;
  78.     }
  79.  
  80.     /* Initialize thread properties */
  81.     p_input->b_eof      = 0;
  82.  
  83.     /* Set target */
  84.     p_input->psz_source = strdup( p_item->psz_uri );
  85.  
  86.     /* Demux */
  87.     p_input->p_demux = NULL;
  88.  
  89.     /* Access */
  90.     p_input->p_access = NULL;
  91.  
  92.     p_input->i_bufsize = 0;
  93.     p_input->i_mtu = 0;
  94.     p_input->i_pts_delay = DEFAULT_PTS_DELAY;
  95.  
  96.     /* Initialize statistics */
  97.     p_input->c_loops                    = 0;
  98.     p_input->stream.c_packets_read      = 0;
  99.     p_input->stream.c_packets_trashed   = 0;
  100.  
  101.     /* Set locks. */
  102.     vlc_mutex_init( p_input, &p_input->stream.stream_lock );
  103.     vlc_cond_init( p_input, &p_input->stream.stream_wait );
  104.     vlc_mutex_init( p_input, &p_input->stream.control.control_lock );
  105.  
  106.     /* Initialize stream description */
  107.     p_input->stream.b_changed = 0;
  108.     p_input->stream.i_es_number = 0;
  109.     p_input->stream.i_selected_es_number = 0;
  110.     p_input->stream.i_pgrm_number = 0;
  111.     p_input->stream.i_new_status = p_input->stream.i_new_rate = 0;
  112.     p_input->stream.b_new_mute = MUTE_NO_CHANGE;
  113.     p_input->stream.i_mux_rate = 0;
  114.     p_input->stream.b_seekable = 0;
  115.     p_input->stream.p_sout = NULL;
  116.  
  117.     /* no stream, no program, no area, no es */
  118.     p_input->stream.p_new_program = NULL;
  119.  
  120.     p_input->stream.i_area_nb = 0;
  121.     p_input->stream.pp_areas = NULL;
  122.     p_input->stream.p_selected_area = NULL;
  123.     p_input->stream.p_new_area = NULL;
  124.  
  125.     p_input->stream.pp_selected_es = NULL;
  126.     p_input->stream.p_removed_es = NULL;
  127.     p_input->stream.p_newly_selected_es = NULL;
  128.  
  129.     /* By default there is one area in a stream */
  130.     input_AddArea( p_input, 0, 1 );
  131.     p_input->stream.p_selected_area = p_input->stream.pp_areas[0];
  132.  
  133.     /* Initialize stream control properties. */
  134.     p_input->stream.control.i_status = PLAYING_S;
  135.     p_input->stream.control.i_rate = DEFAULT_RATE;
  136.     p_input->stream.control.b_mute = 0;
  137.     p_input->stream.control.b_grayscale = config_GetInt( p_input, "grayscale" );
  138.  
  139.     /* Initialize input info */
  140.     p_input->stream.p_info = malloc( sizeof( input_info_category_t ) );
  141.     if( !p_input->stream.p_info )
  142.     {
  143.         msg_Err( p_input, "No memory!" );
  144.         return NULL;
  145.     }
  146.     p_input->stream.p_info->psz_name = strdup("General") ;
  147.     p_input->stream.p_info->p_info = NULL;
  148.     p_input->stream.p_info->p_next = NULL;
  149.  
  150.     msg_Info( p_input, "playlist item `%s'", p_input->psz_source );
  151.  
  152.     p_info = input_InfoCategory( p_input, _("General") );
  153.     input_AddInfo( p_info, _("Playlist Item"), p_input->psz_source );
  154.     vlc_object_attach( p_input, p_parent );
  155.  
  156.     /* Create thread and wait for its readiness. */
  157.     if( vlc_thread_create( p_input, "input", RunThread,
  158.                            VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
  159.     {
  160.         msg_Err( p_input, "cannot create input thread" );
  161.         free( p_input );
  162.         return NULL;
  163.     }
  164.  
  165.     return p_input;
  166. }
  167.  
  168. /*****************************************************************************
  169.  * input_StopThread: mark an input thread as zombie
  170.  *****************************************************************************
  171.  * This function should not return until the thread is effectively cancelled.
  172.  *****************************************************************************/
  173. void input_StopThread( input_thread_t *p_input )
  174. {
  175.     /* Make the thread exit from a possible vlc_cond_wait() */
  176.     vlc_mutex_lock( &p_input->stream.stream_lock );
  177.     /* Request thread destruction */
  178.     p_input->b_die = 1;
  179.  
  180.     vlc_cond_signal( &p_input->stream.stream_wait );
  181.     vlc_mutex_unlock( &p_input->stream.stream_lock );
  182. }
  183.  
  184. /*****************************************************************************
  185.  * input_DestroyThread: mark an input thread as zombie
  186.  *****************************************************************************
  187.  * This function should not return until the thread is effectively cancelled.
  188.  *****************************************************************************/
  189. void input_DestroyThread( input_thread_t *p_input )
  190. {
  191.     /* Join the thread */
  192.     vlc_thread_join( p_input );
  193.  
  194.     /* Destroy Mutex locks */
  195.     vlc_mutex_destroy( &p_input->stream.control.control_lock );
  196.     vlc_cond_destroy( &p_input->stream.stream_wait );
  197.     vlc_mutex_destroy( &p_input->stream.stream_lock );
  198. }
  199.  
  200. /*****************************************************************************
  201.  * RunThread: main thread loop
  202.  *****************************************************************************
  203.  * Thread in charge of processing the network packets and demultiplexing.
  204.  *****************************************************************************/
  205. static int RunThread( input_thread_t *p_input )
  206. {
  207.     /* Signal right now, otherwise we'll get stuck in a peek */
  208.     vlc_thread_ready( p_input );
  209.  
  210.     if( InitThread( p_input ) )
  211.     {
  212.         /* If we failed, wait before we are killed, and exit */
  213.         p_input->b_error = 1;
  214.         ErrorThread( p_input );
  215.         p_input->b_dead = 1;
  216.         return 0;
  217.     }
  218.  
  219.     /* initialization is complete */
  220.     vlc_mutex_lock( &p_input->stream.stream_lock );
  221.     p_input->stream.b_changed = 1;
  222.     vlc_mutex_unlock( &p_input->stream.stream_lock );
  223.  
  224.     while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
  225.     {
  226.         unsigned int i, i_count;
  227.  
  228.         p_input->c_loops++;
  229.  
  230.         vlc_mutex_lock( &p_input->stream.stream_lock );
  231.  
  232.         if( p_input->stream.p_new_program )
  233.         {
  234.             if( p_input->pf_set_program != NULL )
  235.             {
  236.  
  237.                 /* Reinitialize buffer manager. */
  238.                 input_AccessReinit( p_input );
  239.  
  240.                 p_input->pf_set_program( p_input,
  241.                                          p_input->stream.p_new_program );
  242.  
  243.                 /* Escape all decoders for the stream discontinuity they
  244.                  * will encounter. */
  245.                 input_EscapeDiscontinuity( p_input );
  246.  
  247.                 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
  248.                 {
  249.                     pgrm_descriptor_t * p_pgrm
  250.                                             = p_input->stream.pp_programs[i];
  251.  
  252.                     /* Reinitialize synchro. */
  253.                     p_pgrm->i_synchro_state = SYNCHRO_REINIT;
  254.                 }
  255.             }
  256.             p_input->stream.p_new_program = NULL;
  257.         }
  258.  
  259.         if( p_input->stream.p_new_area )
  260.         {
  261.             if( p_input->stream.b_seekable && p_input->pf_set_area != NULL )
  262.             {
  263.                 input_AccessReinit( p_input );
  264.  
  265.                 p_input->pf_set_area( p_input, p_input->stream.p_new_area );
  266.  
  267.                 /* Escape all decoders for the stream discontinuity they
  268.                  * will encounter. */
  269.                 input_EscapeDiscontinuity( p_input );
  270.  
  271.                 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
  272.                 {
  273.                     pgrm_descriptor_t * p_pgrm
  274.                                             = p_input->stream.pp_programs[i];
  275.  
  276.                     /* Reinitialize synchro. */
  277.                     p_pgrm->i_synchro_state = SYNCHRO_REINIT;
  278.                 }
  279.             }
  280.             p_input->stream.p_new_area = NULL;
  281.         }
  282.  
  283.         if( p_input->stream.p_selected_area->i_seek != NO_SEEK )
  284.         {
  285.             if( p_input->stream.b_seekable
  286.                  && p_input->pf_seek != NULL )
  287.             {
  288.                 off_t i_new_pos;
  289.  
  290.                 /* Reinitialize buffer manager. */
  291.                 input_AccessReinit( p_input );
  292.  
  293.                 i_new_pos = p_input->stream.p_selected_area->i_seek;
  294.                 vlc_mutex_unlock( &p_input->stream.stream_lock );
  295.                 p_input->pf_seek( p_input, i_new_pos );
  296.                 vlc_mutex_lock( &p_input->stream.stream_lock );
  297.  
  298.                 /* Escape all decoders for the stream discontinuity they
  299.                  * will encounter. */
  300.                 input_EscapeDiscontinuity( p_input );
  301.  
  302.                 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
  303.                 {
  304.                     pgrm_descriptor_t * p_pgrm
  305.                                             = p_input->stream.pp_programs[i];
  306.  
  307.                     /* Reinitialize synchro. */
  308.                     p_pgrm->i_synchro_state = SYNCHRO_REINIT;
  309.                 }
  310.             }
  311.             p_input->stream.p_selected_area->i_seek = NO_SEEK;
  312.         }
  313.  
  314.         if( p_input->stream.p_removed_es )
  315.         {
  316.             input_UnselectES( p_input, p_input->stream.p_removed_es );
  317.             p_input->stream.p_removed_es = NULL;
  318.         }
  319.  
  320.         if( p_input->stream.p_newly_selected_es )
  321.         {
  322.             input_SelectES( p_input, p_input->stream.p_newly_selected_es );
  323.             p_input->stream.p_newly_selected_es = NULL;
  324.         }
  325.  
  326.         if( p_input->stream.b_new_mute != MUTE_NO_CHANGE )
  327.         {
  328.             if( p_input->stream.b_new_mute )
  329.             {
  330.                 input_EscapeAudioDiscontinuity( p_input );
  331.             }
  332.  
  333.             vlc_mutex_lock( &p_input->stream.control.control_lock );
  334.             p_input->stream.control.b_mute = p_input->stream.b_new_mute;
  335.             vlc_mutex_unlock( &p_input->stream.control.control_lock );
  336.  
  337.             p_input->stream.b_new_mute = MUTE_NO_CHANGE;
  338.         }
  339.  
  340.         vlc_mutex_unlock( &p_input->stream.stream_lock );
  341.  
  342.         /* Read and demultiplex some data. */
  343.         i_count = p_input->pf_demux( p_input );
  344.  
  345.         if( i_count == 0 )
  346.         {
  347.             /* End of file - we do not set b_die because only the
  348.              * playlist is allowed to do so. */
  349.             msg_Info( p_input, "EOF reached" );
  350.             p_input->b_eof = 1;
  351.         }
  352.         else if( i_count < 0 )
  353.         {
  354.             p_input->b_error = 1;
  355.         }
  356.     }
  357.  
  358.     if( p_input->b_error || p_input->b_eof )
  359.     {
  360.         ErrorThread( p_input );
  361.     }
  362.  
  363.     EndThread( p_input );
  364.  
  365.     return 0;
  366. }
  367.  
  368. /*****************************************************************************
  369.  * InitThread: init the input Thread
  370.  *****************************************************************************/
  371. static int InitThread( input_thread_t * p_input )
  372. {
  373.     /* Parse source string. Syntax : [[<access>][/<demux>]:][<source>] */
  374.     char * psz_parser = p_input->psz_dupsource = strdup(p_input->psz_source);
  375.  
  376.     /* Skip the plug-in names */
  377.     while( *psz_parser && *psz_parser != ':' )
  378.     {
  379.         psz_parser++;
  380.     }
  381. #if defined( WIN32 ) || defined( UNDER_CE )
  382.     if( psz_parser - p_input->psz_dupsource == 1 )
  383.     {
  384.         msg_Warn( p_input, "drive letter %c: found in source string",
  385.                            p_input->psz_dupsource[0] ) ;
  386.         psz_parser = "";
  387.     }
  388. #endif
  389.  
  390.     if( !*psz_parser )
  391.     {
  392.         p_input->psz_access = p_input->psz_demux = "";
  393.         p_input->psz_name = p_input->psz_source;
  394.         free( p_input->psz_dupsource );
  395.         p_input->psz_dupsource = NULL;
  396.     }
  397.     else
  398.     {
  399.         *psz_parser++ = '\0';
  400.  
  401.         /* let's skip '//' */
  402.         if( psz_parser[0] == '/' && psz_parser[1] == '/' )
  403.         {
  404.             psz_parser += 2 ;
  405.         }
  406.  
  407.         p_input->psz_name = psz_parser ;
  408.  
  409.         /* Come back to parse the access and demux plug-ins */
  410.         psz_parser = p_input->psz_dupsource;
  411.  
  412.         if( !*psz_parser )
  413.         {
  414.             /* No access */
  415.             p_input->psz_access = "";
  416.         }
  417.         else if( *psz_parser == '/' )
  418.         {
  419.             /* No access */
  420.             p_input->psz_access = "";
  421.             psz_parser++;
  422.         }
  423.         else
  424.         {
  425.             p_input->psz_access = psz_parser;
  426.  
  427.             while( *psz_parser && *psz_parser != '/' )
  428.             {
  429.                 psz_parser++;
  430.             }
  431.  
  432.             if( *psz_parser == '/' )
  433.             {
  434.                 *psz_parser++ = '\0';
  435.             }
  436.         }
  437.  
  438.         if( !*psz_parser )
  439.         {
  440.             /* No demux */
  441.             p_input->psz_demux = "";
  442.         }
  443.         else
  444.         {
  445.             p_input->psz_demux = psz_parser;
  446.         }
  447.     }
  448.  
  449.     msg_Dbg( p_input, "access `%s', demux `%s', name `%s'",
  450.              p_input->psz_access, p_input->psz_demux, p_input->psz_name );
  451.  
  452.     if( input_AccessInit( p_input ) == -1 )
  453.     {
  454.         return -1;
  455.     }
  456.  
  457.     /* Find and open appropriate access module */
  458.     p_input->p_access = module_Need( p_input, "access",
  459.                                      p_input->psz_access );
  460.  
  461.     if ( p_input->p_access == NULL
  462.           && (*p_input->psz_demux || *p_input->psz_access) )
  463.     {
  464.         /* Maybe we got something like :
  465.          * /Volumes/toto:titi/gabu.mpg */
  466.         p_input->psz_access = p_input->psz_demux = "";
  467.         p_input->psz_name = p_input->psz_source;
  468.         free( p_input->psz_dupsource);
  469.         p_input->psz_dupsource = NULL;
  470.  
  471.         p_input->p_access = module_Need( p_input, "access",
  472.                                          p_input->psz_access );
  473.     }
  474.  
  475.     if( p_input->p_access == NULL )
  476.     {
  477.         msg_Err( p_input, "no suitable access module for `%s/%s://%s'",
  478.                  p_input->psz_access, p_input->psz_demux, p_input->psz_name );
  479.         return -1;
  480.     }
  481.  
  482.     /* Waiting for stream. */
  483.     if( p_input->i_mtu )
  484.     {
  485.         p_input->i_bufsize = p_input->i_mtu;
  486.     }
  487.     else
  488.     {
  489.         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
  490.     }
  491.  
  492.     if( p_input->p_current_data == NULL && p_input->pf_read != NULL )
  493.     {
  494.         while( !input_FillBuffer( p_input ) )
  495.         {
  496.             if( p_input->b_die || p_input->b_error || p_input->b_eof )
  497.             {
  498.                 module_Unneed( p_input, p_input->p_access );
  499.                 return -1;
  500.             }
  501.         }
  502.     }
  503.  
  504.     /* Find and open appropriate demux module */
  505.     p_input->p_demux = module_Need( p_input, "demux",
  506.                                     p_input->psz_demux );
  507.  
  508.     if( p_input->p_demux == NULL )
  509.     {
  510.         msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
  511.                  p_input->psz_access, p_input->psz_demux, p_input->psz_name );
  512.         module_Unneed( p_input, p_input->p_access );
  513.         return -1;
  514.     }
  515.  
  516.     /* Initialize optional stream output. */
  517.     psz_parser = config_GetPsz( p_input, "sout" );
  518.     if ( psz_parser != NULL )
  519.     {
  520.         if ( *psz_parser &&
  521.              (p_input->stream.p_sout = sout_NewInstance( p_input, psz_parser ))
  522.                == NULL )
  523.         {
  524.             msg_Err( p_input, "cannot start stream output instance, aborting" );
  525.             free( psz_parser );
  526.             module_Unneed( p_input, p_input->p_access );
  527.             module_Unneed( p_input, p_input->p_demux );
  528.             return -1;
  529.         }
  530.  
  531.         free( psz_parser );
  532.     }
  533.  
  534.     return 0;
  535. }
  536.  
  537. /*****************************************************************************
  538.  * ErrorThread: RunThread() error loop
  539.  *****************************************************************************
  540.  * This function is called when an error occured during thread main's loop.
  541.  *****************************************************************************/
  542. static void ErrorThread( input_thread_t *p_input )
  543. {
  544.     while( !p_input->b_die )
  545.     {
  546.         /* Sleep a while */
  547.         msleep( INPUT_IDLE_SLEEP );
  548.     }
  549. }
  550.  
  551. /*****************************************************************************
  552.  * EndThread: end the input thread
  553.  *****************************************************************************/
  554. static void EndThread( input_thread_t * p_input )
  555. {
  556.     vlc_object_t *p_object;
  557.  
  558. #ifdef HAVE_SYS_TIMES_H
  559.     /* Display statistics */
  560.     struct tms  cpu_usage;
  561.     times( &cpu_usage );
  562.  
  563.     msg_Dbg( p_input, "%ld loops consuming user: %ld, system: %ld",
  564.              p_input->c_loops, cpu_usage.tms_utime, cpu_usage.tms_stime );
  565. #else
  566.     msg_Dbg( p_input, "%ld loops", p_input->c_loops );
  567. #endif
  568.  
  569.     /* Free info structures */
  570.     msg_Dbg( p_input, "freeing info structures...");
  571.     input_DelInfo( p_input );
  572.  
  573.     input_DumpStream( p_input );
  574.  
  575.     /* Free all ES and destroy all decoder threads */
  576.     input_EndStream( p_input );
  577.  
  578.     /* Close optional stream output instance */
  579.     if ( p_input->stream.p_sout != NULL )
  580.     {
  581.         sout_DeleteInstance( p_input->stream.p_sout );
  582.     }
  583.  
  584.     /* Free demultiplexer's data */
  585.     module_Unneed( p_input, p_input->p_demux );
  586.  
  587.     /* Close the access plug-in */
  588.     module_Unneed( p_input, p_input->p_access );
  589.  
  590.     input_AccessEnd( p_input );
  591.  
  592.     /* Close the video output that should have been re-attached
  593.      * to our object */
  594.     p_object = vlc_object_find( p_input, VLC_OBJECT_VOUT, FIND_CHILD );
  595.     if( p_object )
  596.     {
  597.         vlc_object_detach( p_object );
  598.         vlc_object_release( p_object );
  599.         vout_Destroy( (vout_thread_t *)p_object );
  600.     }
  601.  
  602.     free( p_input->psz_source );
  603.     if ( p_input->psz_dupsource != NULL ) free( p_input->psz_dupsource );
  604.  
  605.     /* Tell we're dead */
  606.     p_input->b_dead = 1;
  607. }
  608.  
  609.